############copyright############
############ SCU  2020#####
############Zhou Zunlong#############

'''
矿工各自都维护的内容：
Miner_id: 各自的id，绝对唯一
Chain: 各自维护的一个账本，其实有没有都行，走个形式体现去中心化，因为我不会主动去让矿工质疑链
Current_Node: 就是各自生成的哈希，即需要计算的，因为比特币为了防止抄作业情况，在transaction里都加上了各自矿工的收益，因为大家的id不同，最后默克尔树生成的哈希也各不相同
proof: Pow
'''

'''
所有矿工共享的变量：
Miner_count: 矿工数量 需要加上锁，主要是在新机器加进来的时候自动分配id
Block_Success: 挖矿成功标记；需要存，矿工id、哈希值    （因为是我们自己挖的，所以不用考虑是否会有人恶意占用共享变量

PPow[]: 矿池的工作量证明账本
Time_slice[]: 各个矿工的时间片；用来保证当前时间片用完的矿工要等待，一直等待到大家本次时间片都用完
Mining_Time[]: 挖矿次数
Income[]: 各自的收益，共享是因为如果矿池挖到了还需要分一下收益
Begin[]: 开始挖矿标志，老师似乎是担心先创建了进程还没有start进程就开始运行了，但是理论上不会有这种情况，不过有这个也好，可以做一个开关

老师似乎还考虑了攻击者延迟提交的情况，：Event.wait()
'''
import sys
from Blockchain import Blockchain
import random
import string
import hashlib
import os
import datetime
import time
from utils import read_config

config_file = "config.ini"
config = read_config(config_file)
bwh = config["status"]["bwh"]


def recordTag(ids, str256, strblock, strnonce, stime, trytime):
	strpath=os.path.abspath('..')
	strpath=strpath + "\\" + str(ids) + ".tag"
	folder = os.path.exists(strpath)
	if not folder:           #判断是否存在文件夹如果不存在则创建文件
		with open(strpath,'w') as f:
			f.close()

	with open(strpath,'a') as f:
		#记录挖矿时间
		nowtime  = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
		f.write("time="+ nowtime +"\n")              #挖矿时间
		f.write("time="+ str((datetime.datetime.now()-stime).seconds)+"\n") #从开始到挖矿的时间跨度
		f.write("ids="+str(ids)+"\n")               #记录矿工编号
		f.write("trytime="+str(trytime)+"\n")       #尝试次数
		f.write("hash="+ str256 +"\n")              #记录哈希值
		f.write("block="+ strblock +"\n")           #记录区块值
		f.write("strnonce="+ str(strnonce) +"\n")   #记录随机值
		f.close()
		print("创建" + str(ids) + "tag文件")

def recordRes(ti,ids):
	strpath=os.path.abspath('..')
	strpath=strpath + "/edger.txt"
	folder = os.path.exists(strpath)
	if not folder:           #判断是否存在文件夹如果不存在则创建文件
		with open(strpath,'w') as f:
			f.close()

	with open(strpath,'a') as f:
		#记录挖矿时间
		f.write(str(ti)+","+str(ids)+"\n")    #记录
		f.close()

'''
这里是记录每一步的收益
'''
def recordIncome(M):
	with open('../income.txt', 'a') as f:
		res=""
		for i in M:
			res=res+str(i)+","
		f.write(res[0:-1]+"\n")
		f.close()

def blockRecord():
	strhash = ''.join(random.choices(string.ascii_letters + string.digits, k=256))
	return strhash


def func(ids,z,stime,S,B,U,npro,npow,tunit,T,ti,Share, M, MT,blockdetail,prev_hash,res):
	#Z-探矿难度, strTarget-目标串起始字符串“0000”, starttime=开始时间, S-共享的挖矿成功标志, B-每个矿工开始标志, U-矿工挖矿时间片次数
		#nPro-人数, nPow-算力比例, tUnit-每个时间片挖矿最大次数, T-尝试次数, ti-出块数量, Share-出块收益, M-每个人的收入
    blockchain = Blockchain()
    blockchain.genesis_block()

    strTrans = blockchain.new_trans()
    strBlock = str(ti+1) + strTrans + prev_hash  #strhash保存本次挖矿的区块值，随机字符串
    Z = z                     #难度,前z个哈希值为0，表示到有效块
    sTime = stime             #程序起始时间
    nPro = npro               #矿工进程数量
    nPow = npow[ids]          #矿工算力比例
    tUnit = tunit * nPow      #每一时间片内挖矿次数
    Ti = ti                   #保存出块编号
    nextUnit = True           #控制是否进入下一个时间片


    while B[ids] == 0:
        i=0                   #当主进程尚未开始,一直等待
    while S.value == 0:       #当没有出矿的时候
        kU = 0                #每个时间片内的挖矿次数

        while not nextUnit and S.value == 0: #再进入下一个时间片的挖矿工作前,先检查其他进程矿工是否完成
            nextUnit = True
            for u in range(npro):
                if U[u] < U[ids]:
                    nextUnit = False
        sTime = datetime.datetime.now()

        while kU < tUnit and S.value == 0 :
            T[ids] = T[ids] + 1  #记录该块内的挖矿次数
            kU = kU + 1          #该时间片内的挖矿次数
            strNonce = str(random.randint(1, 1000000))  # 整数神奇数
            strInput = strBlock + strNonce  # 区块与神奇数一起构成哈希输入
            sha256 = hashlib.sha256()  # 创建hash对象
            sha256.update(strInput.encode('utf-8'))
            strRes = sha256.hexdigest()
            if strRes[0:3] == "0" * 3:
                Share[ids] = Share[ids] + 1
            if strRes[0:Z] == "0" * Z and S.value == 0 and (bwh != "1" or ids!=1):
                S.value=1
                nowtime = datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
                print("\n时间", nowtime, "第", ti, "个块，矿工:", ids, "第", T[ids], "次挖矿成功,over:")
                with open("times.csv", "a") as f:
                    f.write(str(T[ids]) + "\n")
                res.value=ids
                blockdetail["id"] = ids
                blockdetail["proof"] = int(strNonce)
                blockdetail["trans"] = strTrans
                # MT[ids] += 1
                for id in range(npro):
                    T[id] = 0
                    U[id] = 0
                # recordIncome(M)
        U[ids] = U[ids] + 1
        nextUnit = False
    # blockchain.new_block(blockdetail["proof"],blockdetail["trans"])
    # print(blockchain.get_chainlen)